package android.framework.rpc.convertor;

import java.util.ArrayList;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class JsonConvertor implements IConvertor<String>{

	private static final String TYPE = "type";
	private static final String NAME = "name";
	private static final String VALUE = "value";
	private static final String IS_CLASS = "isClass";
	private static final String MEMBERS = "members";
	private static final String IS_COLLECTION = "isCollection";
	private static final String ARRAY_LENGTH = "length";
	
	public String convert(MemberInfo memberInfo) {
		try {
			return innerConvert(memberInfo).toString();
		} catch (JSONException e) {
			throw new ConvertorException(e.getMessage());
		}
	}
	
	private JSONObject innerConvert(MemberInfo member) throws JSONException{
		JSONObject jsonObject = new JSONObject();
		jsonObject.put(TYPE, member.getType().getName());
		jsonObject.put(NAME, member.getName());
		if(member.isClass()){
			jsonObject.put(IS_CLASS, true);
			jsonObject.put(IS_COLLECTION, member.isCollection());
			jsonObject.put(ARRAY_LENGTH, member.getArrayLength());
			JSONArray memberArray = new JSONArray();
			for (MemberInfo m : member.getMembers()) {
				memberArray.put(innerConvert(m));
			}
			jsonObject.put(MEMBERS, memberArray);
		}
		else{
			jsonObject.put(IS_CLASS, false);
			jsonObject.put(VALUE, member.getValue());
			
		}
		return jsonObject;
	}

	public MemberInfo convert(String value) throws ConvertorException {
		JSONObject jsonObject;
		try {
			jsonObject = new JSONObject(value);
			return convert(jsonObject);
		} catch (JSONException e) {
			throw new ConvertorException("can't convert string " + value + "to MemberInfo", e);
		}
		
	}
	
	public MemberInfo convert(JSONObject jsonObject) throws ConvertorException, JSONException {
		try {
			String type = jsonObject.getString(TYPE);
			MemberInfo memberInfo;
			Class<?> cls = Class.forName(type);
			if(jsonObject.getBoolean(IS_CLASS)){
				memberInfo = new MemberInfo(cls, new ArrayList<MemberInfo>());
				boolean isCollection = !jsonObject.isNull(IS_COLLECTION) && jsonObject.getBoolean(IS_COLLECTION);
				memberInfo.setCollection(isCollection);
				if(isCollection){
					int length = jsonObject.getInt(ARRAY_LENGTH);
					memberInfo.setArrayLength(length);
				}	
				
				JSONArray memberArray = jsonObject.getJSONArray(MEMBERS);
				for (int i = 0; i < memberArray.length(); i++) {
					memberInfo.getMembers().add(convert(memberArray.getJSONObject(i)));
				}
			}else{
				memberInfo = new MemberInfo(cls, jsonObject.getString(VALUE));
			}
			return memberInfo;
		} catch (ClassNotFoundException e) {
			throw new IllegalArgumentException("can't find class: " + jsonObject.getString(TYPE), e);
		}
	}
}
